Java Database Programming with JDBC Java Database Programming with JDBC
by Pratik Patel
Coriolis, The Coriolis Group
ISBN: 1576100561   Pub Date: 10/01/96
  

Previous Table of Contents Next


Timestamp

The Timestamp class is used to represent a combination of date and time values in the ANSI SQL format YYYY-MM-DD HH:MM:SS.F..., where YYYY is a four-digit year, MM is a two-digit month, DD is a two-digit day, HH is a two-digit hour, MM is a two-digit minute, SS is a two-digit second, and F is an optional fractional second up to nine digits in length. The JDBC Timestamp class extends the existing java.util.Date class (adding the fraction seconds) and, most importantly, adds two methods to convert Strings into timestamps, and vice-versa:

// Create a Timestamp object with a date of 1996-06-30 and a time of
// 2:30:08 pm.
Timestamp t = Timestamp.valueOf("1996-06-30 14:30:08");

// Print the timestamp

System.out.println("Timestamp=" + t.toString());

// Same thing, without leading zeros
Timestamp t2 = Timestamp.valueOf("1996-6-30 14:30:8");
System.out.println("Timestamp=" + t2.toString());

The Timestamp class also serves very well in validating timestamp values. If an invalid time string is passed to the valueOf method, a java.lang.Illegal-ArgumentException is thrown:

String s;

// Get the timestamp from the user
.
.
.
// Validate the timestamp
try {
    Timestamp t = Timestamp.valueOf(s);
}
catch  (java.lang.IllegalArgumentException ex) {
      // Invalid timestamp, notify the application
    .
    .
    .
}

As is the case with the Date class, the Java date epoch is January 1, 1970; therefore, you cannot represent any date values prior to January 1, 1970, with a Timestamp object.

Native Drivers: You’re Not From Around Here, Are Ya?

Before beginning to implement a JDBC driver, the first question that must be answered is: Will this driver be written completely in Java, or will it contain native (machine dependent) code? You may be forced to use native code because many major database systems—such as Oracle, Sybase, and SQLServer—do not provide Java client software. In this case, you will need to write a small library containing C code to bridge from Java to the database client API (the JDBC to ODBC Bridge is a perfect example). The obvious drawback is that the JDBC driver is not portable and cannot be automatically downloaded by today’s browsers.

If a native bridge is required for your JDBC driver, you should keep a few things in mind. First, do as little as possible in the C bridge code; you will want to keep the bridge as small as possible, ideally creating just a Java wrapper around the C API. Most importantly, avoid the temptation of performing memory management in C (i.e. malloc). This is best left in Java code, since the Java Virtual Machine so nicely takes care of garbage collection. Secondly, keep all of the native method declarations in one Java class. By doing so, all of the bridge routines will be localized and much easier to maintain. Finally, don’t make any assumptions about data representation. An integer value may be 2 bytes on one system, and 4 bytes on another. If you are planning to port the native bridge code to a different system (which is highly likely), you should provide native methods that provide the size and interpretation of data.

Listing 10.7 illustrates these suggestions. This module contains all of the native method declarations, as well as the code to load our library. The library will be loaded when the class is instantiated.

Listing 10.7 Java native methods.

//------------------------------------------------------------------------
// MyBridge.java
//
// Sample code to demonstrate the use of native methods
//------------------------------------------------------------------------
package jdbc.test;

import java.sql.*;

public class MyBridge
     extends Object
{
    //--------------------------------------------------------------------
    // Constructor
     // Attempt to load our library. If it can't be loaded, an
     // SQLException will be thrown.
    //--------------------------------------------------------------------
    public MyBridge()
        throws SQLException
    {
        try {
            // Attempt to load our library. For Win95/NT, this will
             // be myBridge.dll. For Unix systems, this will be
            // libmyBridge.so.
              System.loadLibrary("myBridge");
        }
          catch (UnsatisfiedLinkError e) {
              throw new SQLException("Unable to load myBridge library");
        }
    }
    //--------------------------------------------------------------------
    // Native method declarations
//--------------------------------------------------------------------

    // Get the size of an int
    public native int getINTSize();

    // Given a byte array, convert it to an integer value
    public native int getINTValue(byte intValue[]);

    // Call some C function that does something with a String, and
    // returns an integer value.
    public native void callSomeFunction(String stringValue, byte
    intValue[]);
}

Once this module has been compiled (javac), a Java generated header file and C file must be created:

javah   jdbc.test.MyBridge
javah   -stubs  jdbc.test.MyBridge

These files provide the mechanism for the Java and C worlds to communicate with each other. Listing 10.8 shows the generated header file (jdbc_test_MyBridge.h, in this case), which will be included in our C bridge code.

Listing 10.8 Machine-generated header file for native methods.

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <native.h>
/* Header for class jdbc_test_MyBridge */

#ifndef  _Included_jdbc_test_MyBridge
#define  _Included_jdbc_test_MyBridge

typedef struct Classjdbc_test_MyBridge {
     char PAD; /* ANSI C requires structures to have at least one member */
}  Classjdbc_test_MyBridge;
HandleTo(jdbc_test_MyBridge);

#ifdef __cplusplus
extern "C" {
#endif
__declspec(dllexport) long jdbc_test_MyBridge_getINTSize(struct
Hjdbc_test_MyBridge *);
__declspec(dllexport) long jdbc_test_MyBridge_getINTValue(struct
Hjdbc_test_MyBridge *,HArrayOfByte *);
struct Hjava_lang_String;
__declspec(dllexport) void jdbc_test_MyBridge_callSomeFunction(struct
Hjdbc_test_MyBridge *,struct Hjava_lang_String *,HArrayOfByte *);
#ifdef __cplusplus
}
#endif
#endif

The generated C file (shown in Listing 10.9) must be compiled and linked with the bridge.


Previous Table of Contents Next